﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Reflection;
using System.IO;

namespace Walson.Form.Common
{
    [DefaultEvent("ValueChanged")]
    public partial class Slider : Control
    {
        private float _Min = 0;
        /// <summary>
        /// 最小值
        /// </summary>
        public float Min
        {
            get
            {
                return _Min;
            }
            set
            {
                if (_Min != value)
                {
                    _Min = value;
                    if (_Value < _Min)
                        _Value = _Min;

                    this.Invalidate();
                }
            }
        }

        private float _Max = 10;
        /// <summary>
        /// 最大值
        /// </summary>
        public float Max
        {
            get
            {
                return _Max;
            }
            set
            {
                if (_Max != value)
                {
                    _Max = value;
                    if (_Value > _Max)
                        _Value = _Max;

                    this.Invalidate();
                }
            }
        }

        private float _Value = 0;
        /// <summary>
        /// 值
        /// </summary>
        public float Value
        {
            get
            {
                return _Value;
            }
            set
            {
                if (_Value != value)
                {
                    if (value > _Max)
                        value = _Max;
                    if(value<_Min)
                        value = _Min;

                    _Value = value;
                    this.Invalidate();

                    RaiseValueChangedEvent();
                }
            }
        }

        private Orientation _Orientation = Orientation.Vertical;
        /// <summary>
        /// 方向
        /// </summary>
        public Orientation Orientation
        {
            get
            {
                return _Orientation;
            }
            set
            {
                if (_Orientation != value)
                {
                    _Orientation = value;
                    LoadResource();
                    this.Invalidate();
                }
            }
        }

        /// <summary>
        /// 值改变事件处理方法
        /// </summary>
        /// <param name="sender">事件发送者</param>
        public delegate void ValueChangedHandler(object sender);
        /// <summary>
        /// 值改变事件
        /// </summary>
        public event ValueChangedHandler ValueChanged;
        /// <summary>
        /// 触发值改变事件
        /// </summary>
        protected void RaiseValueChangedEvent()
        {
            if (this.ValueChanged != null)
                ValueChanged((object)this);
        }

        private Bitmap _SliderBgTop, _SliderBgCenter, _SliderBgBottom,_Slider,_Bg;
        private bool _MouseDown = false;
        private PointF _MousePoint;
        private Pen _WhitePen;

        /// <summary>
        /// 滑动条
        /// </summary>
        public Slider()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            LoadResource();
            _WhitePen = new Pen(Color.White, 2f);

            this.MouseClick += new MouseEventHandler(Slider_MouseClick);
            this.MouseDown += new MouseEventHandler(Slider_MouseDown);
            this.MouseUp += new MouseEventHandler(Slider_MouseUp);
            this.MouseMove += new MouseEventHandler(Slider_MouseMove);
        }

        void Slider_MouseUp(object sender, MouseEventArgs e)
        {
            _MouseDown = false;
        }

        void Slider_MouseDown(object sender, MouseEventArgs e)
        {
            _MouseDown = true;
        }

        void Slider_MouseMove(object sender, MouseEventArgs e)
        {
            _MousePoint = e.Location;

            if (_MouseDown == false)
                return;

            if (Orientation == Orientation.Vertical)
            {
                float bottomOffset = _Slider.Height;

                Value = (-(e.Y - bottomOffset / 2f - this.Height + bottomOffset) * (_Max - _Min) / (this.Height - bottomOffset)+_Min);
            }
            else
            {
                float leftOffset = _Slider.Width;

                Value = (e.X - leftOffset/2f) * (_Max - _Min) / (this.Width - leftOffset)-_Min;
            }
        }

        void Slider_MouseClick(object sender, MouseEventArgs e)
        {
            if (_MouseDown == false)
                return;

//             float topOffset = _Slider.Height ;
//             float bottomOffset = _Slider.Height ;
// 
//             float sliderPositionY = this.Height - bottomOffset - (this.Height - bottomOffset) * (float)_Value / (_Max - _Min);
//             //if(e.Y>sliderPositionY)
// 
//             Value = (int)(-(e.Y - this.Height + bottomOffset) * (_Max - _Min) / (this.Height - bottomOffset));
            
        }

        private void LoadResource()
        {
            if (_Orientation == Orientation.Vertical)
            {
                Assembly myAssembly = Assembly.GetExecutingAssembly();
                Stream myStream1 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Bottom.png");
                _SliderBgBottom = new Bitmap(myStream1);

                Stream myStream2 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Center.png");
                _SliderBgCenter = new Bitmap(myStream2);

                Stream myStream3 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Top.png");
                _SliderBgTop = new Bitmap(myStream3);

                Stream myStream4 = myAssembly.GetManifestResourceStream("Walson.Resources.Slider.png");
                _Slider = new Bitmap(myStream4);
            }
            else
            {
                Assembly myAssembly = Assembly.GetExecutingAssembly();
                Stream myStream1 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Bottom90.png");
                _SliderBgBottom = new Bitmap(myStream1);

                Stream myStream2 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Center90.png");
                _SliderBgCenter = new Bitmap(myStream2);

                Stream myStream3 = myAssembly.GetManifestResourceStream("Walson.Resources.SliderBg_Top90.png");
                _SliderBgTop = new Bitmap(myStream3);

                Stream myStream4 = myAssembly.GetManifestResourceStream("Walson.Resources.Slider90.png");
                _Slider = new Bitmap(myStream4);
            }
        }

        /// <summary>
        /// 绘图
        /// </summary>
        /// <param name="pe">参数</param>
        protected override void OnPaint(PaintEventArgs pe)
        {
            if (_Orientation == Orientation.Vertical)
            {

                float topOffset = _Slider.Height;
                float bottomOffset = _Slider.Height;

                float sliderPositionY = this.Height - bottomOffset - (this.Height - bottomOffset) * (_Value - _Min) / (_Max - _Min);

                float scalePositionX = 40f * this.Width / _SliderBgTop.Width;

                RectangleF rectTop, rectCenter, rectBottom, rectSlider;
                rectTop = new RectangleF(0, 0, this.Width, _SliderBgTop.Height);
                rectBottom = new RectangleF(0, this.Height - _SliderBgBottom.Height, this.Width, _SliderBgBottom.Height);
                rectCenter = new RectangleF(0, _SliderBgTop.Height, this.Width, this.Height - _SliderBgTop.Height - _SliderBgBottom.Height + 5);
                rectSlider = new RectangleF(0, sliderPositionY, (float)this.Width / (float)_SliderBgTop.Width * (float)_Slider.Width, _Slider.Height);


                using (Bitmap bmp = new Bitmap(this.Width, this.Height))
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.TextRenderingHint = TextRenderingHint.AntiAlias;

                        g.Clear(Color.Transparent);

                        g.DrawImage(_SliderBgTop, rectTop, new RectangleF(0, 0, _SliderBgTop.Width, _SliderBgTop.Height), GraphicsUnit.Pixel);
                        g.DrawImage(_SliderBgCenter, rectCenter, new RectangleF(0, 0, _SliderBgCenter.Width, _SliderBgCenter.Height), GraphicsUnit.Pixel);
                        g.DrawImage(_SliderBgBottom, rectBottom, new RectangleF(0, 0, _SliderBgBottom.Width, _SliderBgBottom.Height), GraphicsUnit.Pixel);

                        PointF[] line = new PointF[3];
                        line[0] = new PointF(0, 0);
                        line[1] = new PointF(-5, 0);
                        line[2] = new PointF(-10, 0);

                        float gap = (float)(this.Height - bottomOffset) / (float)(_Max - _Min);
                        //g.TranslateTransform(scalePositionX, startY);
                        for (int i = 0; i <= _Max-_Min; i++)
                        {
                            line[0] = new PointF(scalePositionX, this.Height - bottomOffset / 2f - i * gap);
                            line[1] = new PointF(scalePositionX - 5, this.Height - bottomOffset / 2f - i * gap);
                            g.DrawLine(_WhitePen, line[0], line[1]);
                        }

                        g.DrawImage(_Slider, rectSlider, new RectangleF(0, 0, _Slider.Width, _Slider.Height), GraphicsUnit.Pixel);
                    }
                    pe.Graphics.DrawImage(bmp, 0, 0);


                }
            }
            else
            {
                float leftOffset = _Slider.Width;

                float sliderPositionX = (this.Width - leftOffset) * (_Value - _Min) / (_Max - _Min);

                float scalePositionY = 40f * this.Height / _SliderBgTop.Height;

                RectangleF rectLeft, rectCenter, rectRight, rectSlider;
                rectLeft= new RectangleF(0, 0, _SliderBgBottom.Width, this.Height);
                rectRight = new RectangleF( this.Width - _SliderBgTop.Width,0, _SliderBgTop.Width, this.Height);
                rectCenter = new RectangleF(_SliderBgBottom.Width, 0, this.Width - rectLeft.Width - rectRight.Width + 7, this.Height);
                rectSlider = new RectangleF(sliderPositionX, 0, _Slider.Width, (float)this.Height / (float)_SliderBgTop.Height * (float)_Slider.Height);


                using (Bitmap bmp = new Bitmap(this.Width, this.Height))
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.TextRenderingHint = TextRenderingHint.AntiAlias;

                        g.Clear(Color.Transparent);

                        g.DrawImage(_SliderBgTop, rectRight, new RectangleF(0, 0, _SliderBgTop.Width, _SliderBgTop.Height), GraphicsUnit.Pixel);
                        g.DrawImage(_SliderBgCenter, rectCenter, new RectangleF(0, 0, _SliderBgCenter.Width, _SliderBgCenter.Height), GraphicsUnit.Pixel);
                        g.DrawImage(_SliderBgBottom, rectLeft, new RectangleF(0, 0, _SliderBgBottom.Width, _SliderBgBottom.Height), GraphicsUnit.Pixel);

                        //g.DrawString(this.Value.ToString(), this.Font, Brushes.White, 10, 10);

                        PointF[] line = new PointF[3];
                        line[0] = new PointF(0, 0);
                        line[1] = new PointF(-5, 0);
                        line[2] = new PointF(-10, 0);

                        float gap = (float)(this.Width - leftOffset) / (float)(_Max - _Min);
                        //g.TranslateTransform(scalePositionX, startY);
                        for (int i = 0; i <= _Max-_Min; i++)
                        {
                            line[0] = new PointF(this.Width - leftOffset / 2f - i * gap,scalePositionY);
                            line[1] = new PointF(this.Width - leftOffset / 2f - i * gap, scalePositionY - 5);
                            g.DrawLine(_WhitePen, line[0], line[1]);
                        }

                        g.DrawImage(_Slider, rectSlider, new RectangleF(0, 0, _Slider.Width, _Slider.Height), GraphicsUnit.Pixel);
                    }
                    pe.Graphics.DrawImage(bmp, 0, 0);


                }


                
            }
            base.OnPaint(pe);


        }
    }
}
